home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / ds3100.md / machAsm.s < prev    next >
Text File  |  1992-12-18  |  49KB  |  1,996 lines

  1. /*
  2.  * machAsm.s --
  3.  *
  4.  *    Contains misc. assembler routines for the PMAX.
  5.  *
  6.  *    Copyright (C) 1989 Digital Equipment Corporation.
  7.  *    Permission to use, copy, modify, and distribute this software and
  8.  *    its documentation for any purpose and without fee is hereby granted,
  9.  *    provided that the above copyright notice appears in all copies.  
  10.  *    Digital Equipment Corporation makes no representations about the
  11.  *    suitability of this software for any purpose.  It is provided "as is"
  12.  *    without express or implied warranty.
  13.  *
  14.  * $Header: /cdrom/src/kernel/Cvsroot/kernel/mach/ds3100.md/machAsm.s,v 9.15 92/08/04 15:41:49 shirriff Exp $ SPRITE (DECWRL)
  15.  */
  16.  
  17. #include "machConst.h"
  18. #include "machAsmDefs.h"
  19. #include "vmPmaxConst.h"
  20. #include <regdef.h>
  21.  
  22. /*----------------------------------------------------------------------------
  23.  *
  24.  * MachConfigCache --
  25.  *
  26.  *    Size the caches.
  27.  *
  28.  * Results:
  29.  *         None.
  30.  *
  31.  * Side effects:
  32.  *    The size of the data cache stored into machDataCacheSize and the
  33.  *    size of instruction cache stored into machInstCacheSize.
  34.  *
  35.  *----------------------------------------------------------------------------
  36.  */
  37. CONFIG_FRAME=    (4*4)+4+4        # 4 arg saves, ra, and a saved register
  38.     .globl    MachConfigCache
  39. MachConfigCache:
  40.     subu    sp,CONFIG_FRAME
  41.     sw    ra,CONFIG_FRAME-4(sp)        # Save return address.
  42.     sw    s0,CONFIG_FRAME-8(sp)        # Save s0 on stack.
  43.     mfc0    s0,MACH_COP_0_STATUS_REG    # Save status register.
  44.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  45.     .set    noreorder
  46.     la    v0,1f
  47.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  48.     j    v0
  49.     nop
  50.  
  51. 1:    jal    SizeCache            # Get the size of the d-cache.
  52.     nop
  53.     sw    v0,machDataCacheSize
  54.     nop                    # Make sure sw out of pipe
  55.     nop
  56.     nop
  57.     nop
  58.     li    v0,MACH_SR_SWAP_CACHES        # Swap caches
  59.     mtc0    v0,MACH_COP_0_STATUS_REG
  60.     nop                    # Insure caches stable
  61.     nop
  62.     nop
  63.     nop
  64.     jal    SizeCache            # Get the size of the i-cache.
  65.     nop
  66.     sw    v0,machInstCacheSize        
  67.     nop                    # Make sure sw out of pipe
  68.     nop
  69.     nop
  70.     nop
  71.     mtc0    zero, MACH_COP_0_STATUS_REG    # Swap back caches. 
  72.     nop
  73.     nop
  74.     nop
  75.     nop
  76.     la    t0,1f
  77.     j    t0                # Back to cached mode
  78.     nop
  79.  
  80. 1:    mtc0    s0,MACH_COP_0_STATUS_REG    # Restore status register.
  81.     nop
  82.     lw    s0,CONFIG_FRAME-8(sp)        # Restore old s0
  83.     lw    ra,CONFIG_FRAME-4(sp)        # Restore return addr
  84.     addu    sp,CONFIG_FRAME            # Restore sp.
  85.     j    ra
  86.     nop
  87.     .set    reorder
  88.  
  89. /*----------------------------------------------------------------------------
  90.  *
  91.  * SizeCache --
  92.  *
  93.  *    Get the size of the cache.
  94.  *
  95.  * Results:
  96.  *         The size of the cache.
  97.  *
  98.  * Side effects:
  99.  *    None.
  100.  *
  101.  *----------------------------------------------------------------------------
  102.  */
  103. SizeCache:
  104.     .set    noreorder
  105.     mfc0    t0,MACH_COP_0_STATUS_REG    # Save the current status reg.
  106.     nop                
  107.     or    v0,t0,MACH_SR_ISOL_CACHES    # Isolate the caches.
  108.     nop                    # Make sure no stores in pipe
  109.     mtc0    v0,MACH_COP_0_STATUS_REG
  110.     nop                    # Make sure isolated
  111.     nop
  112.     nop
  113.     /*
  114.      * Clear cache size boundaries.
  115.      */
  116.     li    v0, MACH_MIN_CACHE_SIZE
  117. 1:
  118.     sw    zero, VMMACH_PHYS_CACHED_START(v0)
  119.     sll    v0,1
  120.     ble    v0,+MACH_MAX_CACHE_SIZE,1b
  121.     nop
  122.     li    v0,-1
  123.     sw    v0, VMMACH_PHYS_CACHED_START(zero)    # Store marker in cache
  124.     li    v0, MACH_MIN_CACHE_SIZE
  125.  
  126. 2:    lw    v1, VMMACH_PHYS_CACHED_START(v0)    # Look for marker
  127.     nop            
  128.     bne    v1,zero,3f                # Found marker.
  129.     nop
  130.  
  131.     sll    v0,1            # cache size * 2
  132.     ble    v0,+MACH_MAX_CACHE_SIZE,2b        # keep looking
  133.     nop
  134.     move    v0,zero            # must be no cache
  135.     .set    reorder
  136.  
  137. 3:    mtc0    t0,MACH_COP_0_STATUS_REG
  138.     nop                # Make sure unisolated
  139.     nop
  140.     nop
  141.     nop
  142.     j    ra
  143.     nop
  144. .set reorder
  145.  
  146. /*----------------------------------------------------------------------------
  147.  *
  148.  * MachFlushCache --
  149.  *
  150.  *    Flush the caches.
  151.  *
  152.  * Results:
  153.  *         None.
  154.  *
  155.  * Side effects:
  156.  *    The contents of the cache is flushed.
  157.  *
  158.  *----------------------------------------------------------------------------
  159.  */
  160.     .globl    MachFlushCache
  161. MachFlushCache:
  162.     lw    t1,machInstCacheSize        # Must load before isolating
  163.     lw    t2,machDataCacheSize        # Must load before isolating
  164.     mfc0    t3,MACH_COP_0_STATUS_REG     # Save the status register.
  165.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  166.     .set    noreorder
  167.     la    v0,1f
  168.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  169.     j    v0            
  170.     nop
  171.  
  172.     /*
  173.      * flush text cache
  174.      */
  175. 1:    li    v0,MACH_SR_ISOL_CACHES|MACH_SR_SWAP_CACHES
  176.     mtc0    v0,MACH_COP_0_STATUS_REG    # Isolate and swap caches.
  177.     li    t0,VMMACH_PHYS_UNCACHED_START
  178.     subu    t0,t1
  179.     li    t1,VMMACH_PHYS_UNCACHED_START
  180.     la    v0,1f                # Run cached
  181.     j    v0
  182.     nop
  183.     .set    reorder
  184.  
  185. 1:    sb    zero,0(t0)
  186.     sb    zero,4(t0)
  187.     sb    zero,8(t0)
  188.     sb    zero,12(t0)
  189.     sb    zero,16(t0)
  190.     sb    zero,20(t0)
  191.     sb    zero,24(t0)
  192.     addu    t0,32
  193.     sb    zero,-4(t0)
  194.     bne    t0,t1,1b
  195.  
  196.     .set    noreorder
  197.     la    v0,1f
  198.     or    v0,VMMACH_PHYS_UNCACHED_START
  199.     j    v0                # Run uncached
  200.     nop
  201.  
  202.     /*
  203.      * flush data cache
  204.      */
  205. 1:    li    v0,MACH_SR_ISOL_CACHES|MACH_SR_SWAP_CACHES
  206.     mtc0    v0,MACH_COP_0_STATUS_REG    # Isolate and swap back caches
  207.     li    t0,VMMACH_PHYS_UNCACHED_START
  208.     subu    t0,t2
  209.     la    v0,1f
  210.     j    v0                # Back to cached mode
  211.     nop
  212.     .set    reorder
  213.  
  214. 1:    sb    zero,0(t0)
  215.     sb    zero,4(t0)
  216.     sb    zero,8(t0)
  217.     sb    zero,12(t0)
  218.     sb    zero,16(t0)
  219.     sb    zero,20(t0)
  220.     sb    zero,24(t0)
  221.     addu    t0,32
  222.     sb    zero,-4(t0)
  223.     bne    t0,t1,1b
  224.  
  225.     .set    noreorder
  226.     nop                    # Insure isolated stores 
  227.     nop                    #     out of pipe.
  228.     nop
  229.     mtc0    t3,MACH_COP_0_STATUS_REG    # Restore status reg.
  230.     nop                    # Insure cache unisolated.
  231.     nop
  232.     nop
  233.     nop
  234.     .set    reorder
  235.     j    ra
  236.  
  237. /*----------------------------------------------------------------------------
  238.  *
  239.  * MachCleanICache --
  240.  *
  241.  *    MachCleanICache(addr, len)
  242.  *
  243.  *    Flush i cache for range ofaddr to addr + len - 1.
  244.  *
  245.  * Results:
  246.  *         None.
  247.  *
  248.  * Side effects:
  249.  *    The contents of the cache is flushed.
  250.  *
  251.  *----------------------------------------------------------------------------
  252.  */
  253.     .globl MachCleanICache
  254. MachCleanICache:
  255.     lw    t1,machInstCacheSize
  256.     mfc0    t3,MACH_COP_0_STATUS_REG    # Save SR
  257.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  258.  
  259.     .set    noreorder
  260.     la    v0,1f
  261.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  262.     j    v0
  263.     nop
  264.  
  265. 1:    li    v0,MACH_SR_ISOL_CACHES|MACH_SR_SWAP_CACHES
  266.     mtc0    v0,MACH_COP_0_STATUS_REG
  267.     bltu    t1,a1,1f        # cache is smaller than region
  268.     nop
  269.     move    t1,a1
  270. 1:    addu    t1,a0            # ending address + 1
  271.     move    t0,a0
  272.     la    v0,1f            # run cached
  273.     j    v0
  274.     nop
  275.     .set    reorder
  276.  
  277. 1:    sb    zero,0(t0)
  278.     sb    zero,4(t0)
  279.     sb    zero,8(t0)
  280.     sb    zero,12(t0)
  281.     sb    zero,16(t0)
  282.     sb    zero,20(t0)
  283.     sb    zero,24(t0)
  284.     addu    t0,32
  285.     sb    zero,-4(t0)
  286.     bltu    t0,t1,1b
  287.  
  288.     .set    noreorder
  289.     la    v0,1f
  290.     or    v0,VMMACH_PHYS_UNCACHED_START
  291.     j    v0            # Run uncached
  292.     nop
  293.  
  294. 1:    nop                # insure isolated stores out of pipe
  295.     mtc0    zero,MACH_COP_0_STATUS_REG  # unisolate, unswap
  296.     nop                # keep pipeline clean
  297.     nop                # keep pipeline clean
  298.     nop                # keep pipeline clean
  299.     mtc0    t3,MACH_COP_0_STATUS_REG # enable interrupts
  300.     nop
  301.     j    ra            # return and run cached
  302.     nop
  303.     .set    reorder
  304.  
  305.     .globl MachFetchICache
  306. MachFetchICache:
  307.     mfc0    t3,MACH_COP_0_STATUS_REG    # Save SR
  308.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  309.  
  310.     .set    noreorder
  311.     la    v0,1f
  312.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  313.     j    v0
  314.     nop
  315.  
  316. 1:    li    v0,MACH_SR_ISOL_CACHES|MACH_SR_SWAP_CACHES
  317.     mtc0    v0,MACH_COP_0_STATUS_REG
  318.     la    v0,1f            # run cached
  319.     j    v0
  320.     nop
  321. 1:    ld    v0, 0(a0)
  322.     nop
  323.  
  324.     la    t0,1f
  325.     or    t0,VMMACH_PHYS_UNCACHED_START
  326.     j    t0            # Run uncached
  327.     nop
  328.  
  329. 1:    mtc0    zero, MACH_COP_0_STATUS_REG  # unisolate, unswap
  330.     nop                # keep pipeline clean
  331.     nop                # keep pipeline clean
  332.     nop                # keep pipeline clean
  333.     mtc0    t3,MACH_COP_0_STATUS_REG # enable interrupts
  334.     nop
  335.     j    ra            # return and run cached
  336.     nop
  337.     .set    reorder
  338.  
  339.  
  340.  
  341. /*----------------------------------------------------------------------------
  342.  *
  343.  * MachRunUserProc --
  344.  *
  345.  *    MachRunUserProc(pc, sp)
  346.  *        Address    pc;    * The program counter to execute at.
  347.  *        Address sp;    * The stack pointer to start with.
  348.  *
  349.  *    Start a process running in user mode.  We are called with interrupts
  350.  *    disabled.  
  351.  *
  352.  *
  353.  * Results:
  354.  *         None.
  355.  *
  356.  * Side effects:
  357.  *    The status register and stack pointer are modified.
  358.  *
  359.  *----------------------------------------------------------------------------
  360.  */
  361. LEAF(MachRunUserProc)
  362. .set noreorder
  363.     subu    sp, sp, STAND_FRAME_SIZE
  364.     sw        ra, STAND_RA_OFFSET(sp)
  365.     sw        a0, STAND_FRAME_SIZE(sp)
  366.     sw        a1, STAND_FRAME_SIZE + 4(sp)
  367.     .mask    0x80000000, -4
  368.     li        t0, (MACH_KERN_INT_MASK|MACH_SR_KU_PREV|MACH_SR_INT_ENA_PREV)
  369.     mtc0    t0, MACH_COP_0_STATUS_REG
  370.     lw        k0, machCurStatePtr
  371.     addu    k1, a0, zero
  372. .set noat
  373.     RESTORE_REGS(k0, MACH_TRAP_REGS_OFFSET)
  374. .set at
  375.  
  376.     j        k1
  377.     rfe
  378. .set reorder
  379. END(MachRunUserProc)
  380.  
  381. /*----------------------------------------------------------------------------
  382.  *
  383.  * MachException --
  384.  *
  385.  *    Handle a general exception.
  386.  *
  387.  *
  388.  * Results:
  389.  *         None.
  390.  *
  391.  * Side effects:
  392.  *    None.
  393.  *
  394.  *----------------------------------------------------------------------------
  395.  */
  396.     .globl MachException
  397. MachException:
  398. .set noat
  399. /*
  400.  * Find out what mode we came from.
  401.  */
  402.     mfc0    k0, MACH_COP_0_STATUS_REG
  403.     and        k0, k0, MACH_SR_KU_PREV
  404.     bne        k0, zero, 1f
  405.     j        MachKernException
  406. 1:  j        MachUserException
  407. .set at
  408.     .globl MachEndException
  409. MachEndException:
  410.  
  411. /*----------------------------------------------------------------------------
  412.  *
  413.  * MachKernException --
  414.  *
  415.  *    Handle an exception from kernel mode.
  416.  *
  417.  * Results:
  418.  *         None.
  419.  *
  420.  * Side effects:
  421.  *    None.
  422.  *
  423.  *----------------------------------------------------------------------------
  424.  */
  425.     .globl MachKernException
  426. MachKernException:
  427. /*
  428.  * Determine the type of fault and jump to the appropriate routine.
  429.  */
  430. .set noreorder
  431. .set noat
  432.     mfc0    k0, MACH_COP_0_CAUSE_REG    # Get the cause register value.
  433.     la        k1, machKernExcTable        # Load base of the func table.
  434.     and        k0, k0, MACH_CR_EXC_CODE    # Mask out the cause bits. 
  435.     addu    k0, k0, k1            # Get the address of the
  436.                         #    function entry.  Note that
  437.                         #    the cause is already 
  438.                         #    shifted left by 2 bits so
  439.                         #    we don't have to shift.
  440.     lw        k0, 0(k0)            # Get the function address
  441.     nop
  442.     j        k0                # Jump to the function.
  443.     nop
  444. .set at
  445. .set reorder
  446.  
  447.  
  448. /*----------------------------------------------------------------------------
  449.  *
  450.  * Mach_KernGenException --
  451.  *
  452.  *    Handle an exception from kernel mode.
  453.  *
  454.  * Results:
  455.  *         None.
  456.  *
  457.  * Side effects:
  458.  *    None.
  459.  *
  460.  *----------------------------------------------------------------------------
  461.  */
  462.  
  463. /*
  464.  * The kernel exception stack contains 28 saved general registers, the
  465.  * status register and the cause register and the multiply lo and high 
  466.  * registers.  In addition we need to set
  467.  * this up for linkage conventions.
  468.  */
  469. #define    KERN_EXC_FRAME_SIZE    (STAND_FRAME_SIZE + 8 + SAVED_REG_SIZE + 8)
  470. #define KERN_SR_OFFSET        (STAND_FRAME_SIZE)
  471. #define CAUSE_OFFSET        (STAND_FRAME_SIZE + 4)
  472. #define SAVED_REG_OFFSET    (STAND_FRAME_SIZE + 8)
  473. #define KERN_MULT_LO_OFFSET    (STAND_FRAME_SIZE + 8 + SAVED_REG_SIZE)
  474. #define KERN_MULT_HI_OFFSET    (STAND_FRAME_SIZE + 8 + SAVED_REG_SIZE + 4)
  475.  
  476. NON_LEAF(Mach_KernGenException,KERN_EXC_FRAME_SIZE,ra)
  477. .set noreorder
  478. .set noat
  479.     subu    sp, sp, KERN_EXC_FRAME_SIZE
  480. /*
  481.  * Save kernel registers onto the stack.
  482.  */
  483.     SAVE_KERNEL_REGS(SAVED_REG_OFFSET)
  484.     mflo    t0
  485.     sw        t0, KERN_MULT_LO_OFFSET(sp)
  486.     mfhi    t0
  487.     sw        t0, KERN_MULT_HI_OFFSET(sp)
  488. /*
  489.  * Save the rest of the state.
  490.  */
  491.     mfc0    k0, MACH_COP_0_EXC_PC
  492.     mfc0    k1, MACH_COP_0_STATUS_REG
  493.     sw        k0, STAND_RA_OFFSET(sp)
  494.     .mask    0x80000000, (STAND_RA_OFFSET - KERN_EXC_FRAME_SIZE)
  495.     sw        k1, KERN_SR_OFFSET(sp)
  496.     mfc0    k0, MACH_COP_0_CAUSE_REG
  497.     nop
  498.     sw        k0, CAUSE_OFFSET(sp)
  499.  
  500. /*
  501.  * Call the exception handler.
  502.  */
  503.     mfc0    a0, MACH_COP_0_STATUS_REG    # First arg is the status reg.
  504.     mfc0    a1, MACH_COP_0_CAUSE_REG    # Second arg is the cause reg.
  505.     mfc0    a2, MACH_COP_0_BAD_VADDR    # Third arg is the fault addr.
  506.     mfc0    a3, MACH_COP_0_EXC_PC        # Fourth arg is the pc.
  507.     jal        MachKernelExceptionHandler
  508.     nop
  509.     mtc0    zero, MACH_COP_0_STATUS_REG    # Disable interrupts
  510.     nop
  511. /*
  512.  * Check error code.
  513.  */
  514.     li        t0, MACH_OK
  515.     li        t1, MACH_USER_ERROR
  516.     beq        v0, t0, 9f
  517.     nop
  518.     beq        v0, t1, 8f
  519.     nop
  520.  
  521. /*
  522.  * We got a kernel error.  Save the special registers that we saved on 
  523.  * the stack into the debug state struct.
  524.  */
  525.     lw        k0, machDebugStatePtr
  526.     lw        k1, KERN_SR_OFFSET(sp)
  527.     nop
  528.     sw        k1, MACH_DEBUG_STATUS_REG_OFFSET(k0)
  529.     lw        k1, STAND_RA_OFFSET(sp)
  530.     nop
  531.     sw        k1, MACH_DEBUG_EXC_PC_OFFSET(k0)
  532.     lw        k1, CAUSE_OFFSET(sp)
  533.     nop
  534.     sw        k1, MACH_DEBUG_CAUSE_REG_OFFSET(k0)
  535.  
  536. /*
  537.  * Restore kernel registers and pop the stack.
  538.  */
  539.     lw        t0, KERN_MULT_LO_OFFSET(sp)
  540.     lw        t1, KERN_MULT_HI_OFFSET(sp)
  541.     mtlo    t0
  542.     mthi    t1
  543.     RESTORE_KERNEL_REGS(SAVED_REG_OFFSET)
  544.     addu    sp, sp, KERN_EXC_FRAME_SIZE
  545.  
  546. /*
  547.  * Save the general registers into the debug state struct.
  548.  */
  549.     SAVE_REGS(k0, MACH_DEBUG_REGS_OFFSET)
  550.     sw        gp, MACH_DEBUG_REGS_OFFSET +  (4 * GP)(k0)
  551.     sw        sp, MACH_DEBUG_REGS_OFFSET +  (4 * SP)(k0)
  552.     mflo    t0
  553.     sw        t0, MACH_DEBUG_MULT_LO_OFFSET(k0)
  554.     mfhi    t0
  555.     sw        t0, MACH_DEBUG_MULT_HI_OFFSET(k0)
  556.  
  557. /*
  558.  * Now save the rest of the special registers.
  559.  */
  560.     mfc0    t0, MACH_COP_0_TLB_INDEX
  561.     nop
  562.     sw        t0, MACH_DEBUG_TLB_INDEX_OFFSET(k0)
  563.     mfc0    t0, MACH_COP_0_TLB_RANDOM
  564.     nop
  565.     sw        t0, MACH_DEBUG_TLB_RANDOM_OFFSET(k0)
  566.     mfc0    t0, MACH_COP_0_TLB_LOW
  567.     nop
  568.     sw        t0, MACH_DEBUG_TLB_LOW_OFFSET(k0)
  569.     mfc0    t0, MACH_COP_0_TLB_CONTEXT
  570.     nop
  571.     sw        t0, MACH_DEBUG_TLB_CONTEXT_OFFSET(k0)
  572.     mfc0    t0, MACH_COP_0_BAD_VADDR
  573.     nop
  574.     sw        t0, MACH_DEBUG_BAD_VADDR_OFFSET(k0)
  575.     mfc0    t0, MACH_COP_0_TLB_HI
  576.     nop
  577.     sw        t0, MACH_DEBUG_TLB_HI_OFFSET(k0)
  578. /*
  579.  * Save the floating point state.
  580.  */
  581.  
  582. .set at
  583.     mfc0    t0, MACH_COP_0_STATUS_REG
  584.     nop
  585.     or        t0, t0, MACH_SR_COP_1_BIT
  586.     mtc0    t0, MACH_COP_0_STATUS_REG
  587.     nop
  588.     nop
  589.     cfc1    t1, MACH_FPC_CSR
  590.     nop
  591.     sw        t1, MACH_DEBUG_FPC_CSR_REG_OFFSET(k0)
  592.  
  593. #define SAVE_DEBUG_CP1_REG(reg) \
  594.     swc1    $f/**/reg, MACH_DEBUG_FP_REGS_OFFSET+reg*4(k0)
  595.  
  596.     SAVE_DEBUG_CP1_REG(0);  SAVE_DEBUG_CP1_REG(1);  SAVE_DEBUG_CP1_REG(2)
  597.     SAVE_DEBUG_CP1_REG(3);  SAVE_DEBUG_CP1_REG(4);  SAVE_DEBUG_CP1_REG(5)
  598.     SAVE_DEBUG_CP1_REG(6);  SAVE_DEBUG_CP1_REG(7);  SAVE_DEBUG_CP1_REG(8)
  599.     SAVE_DEBUG_CP1_REG(9);  SAVE_DEBUG_CP1_REG(10); SAVE_DEBUG_CP1_REG(11)
  600.     SAVE_DEBUG_CP1_REG(12); SAVE_DEBUG_CP1_REG(13); SAVE_DEBUG_CP1_REG(14)
  601.     SAVE_DEBUG_CP1_REG(15); SAVE_DEBUG_CP1_REG(16); SAVE_DEBUG_CP1_REG(17)
  602.     SAVE_DEBUG_CP1_REG(18); SAVE_DEBUG_CP1_REG(19); SAVE_DEBUG_CP1_REG(20)
  603.     SAVE_DEBUG_CP1_REG(21); SAVE_DEBUG_CP1_REG(22); SAVE_DEBUG_CP1_REG(23)
  604.     SAVE_DEBUG_CP1_REG(24); SAVE_DEBUG_CP1_REG(25); SAVE_DEBUG_CP1_REG(26)
  605.     SAVE_DEBUG_CP1_REG(27); SAVE_DEBUG_CP1_REG(28); SAVE_DEBUG_CP1_REG(29)
  606.     SAVE_DEBUG_CP1_REG(30); SAVE_DEBUG_CP1_REG(31)
  607. .set noat
  608.  
  609. /*
  610.  * Switch to the debuggers stack and call the debugger.  The debuggers
  611.  * stack starts at the base of the first kernel stack.
  612.  */
  613.     li        sp, MACH_STACK_BOTTOM - STAND_FRAME_SIZE
  614.     jal        Dbg_Main
  615.     nop
  616. /*
  617.  * The debugger returns the PC to continue at.
  618.  */
  619.     addu    k1, v0, 0
  620.     lw        k0, machDebugStatePtr
  621.     nop
  622.  
  623.     lw        t0, MACH_TRAP_MULT_LO_OFFSET(k0)
  624.     lw        t1, MACH_TRAP_MULT_HI_OFFSET(k0)
  625.     mtlo    t0
  626.     mthi    t1
  627.     RESTORE_REGS(k0, MACH_DEBUG_REGS_OFFSET)
  628.     lw        k0, MACH_DEBUG_STATUS_REG_OFFSET(k0)
  629.     nop
  630.     mtc0    k0, MACH_COP_0_STATUS_REG    
  631.     nop
  632.     j        k1
  633.     rfe
  634.  
  635. 8:
  636. /*
  637.  * We got an error on a cross address space copy.  All we have to do is
  638.  * restore the stack pointer and the status register, set the return value
  639.  * register and return.
  640.  */
  641.     lw        t0, KERN_MULT_LO_OFFSET(sp)
  642.     lw        t1, KERN_MULT_HI_OFFSET(sp)
  643.     mtlo    t0
  644.     mthi    t1
  645.     RESTORE_KERNEL_REGS(SAVED_REG_OFFSET)
  646.     lui        v0, 0x2                # v0 <= SYS_ARG_NO_ACCESS
  647.     lw        k0, KERN_SR_OFFSET(sp)        # Get the saved sp.
  648.     addu    sp, sp, KERN_EXC_FRAME_SIZE    # Clear off the stack.
  649.     mtc0    k0, MACH_COP_0_STATUS_REG    # Restore the status register.
  650.     nop
  651.     j        ra                # Now return to the caller
  652.     rfe                        #   who caused the error.
  653.  
  654.  
  655. 9:
  656. /*
  657.  * Restore registers and return from the exception.
  658.  */
  659.     lw        t0, KERN_MULT_LO_OFFSET(sp)
  660.     lw        t1, KERN_MULT_HI_OFFSET(sp)
  661.     mtlo    t0
  662.     mthi    t1
  663.     RESTORE_KERNEL_REGS(SAVED_REG_OFFSET)
  664.  
  665.     lw        k0, KERN_SR_OFFSET(sp)
  666.     lw        k1, STAND_RA_OFFSET(sp)
  667.     addu    sp, sp, KERN_EXC_FRAME_SIZE
  668.     mtc0    k0, MACH_COP_0_STATUS_REG    # Restore the SR
  669.     nop
  670.     j        k1                # Now return from the
  671.     rfe                        #    exception.
  672. END(Mach_KernGenException)
  673.     .set at
  674.     .set reorder
  675.  
  676. /*----------------------------------------------------------------------------
  677.  *
  678.  * MachUserException --
  679.  *
  680.  *    Handle an exception from user mode.
  681.  *
  682.  * Results:
  683.  *         None.
  684.  *
  685.  * Side effects:
  686.  *    None.
  687.  *
  688.  *----------------------------------------------------------------------------
  689.  */
  690.     .globl MachUserException
  691. MachUserException:
  692. .set noreorder
  693. .set noat
  694.     mfc0    k0, MACH_COP_0_CAUSE_REG    # Get the cause register value.
  695.     la        k1, machUserExcTable        # Load base of the func table.
  696.     and        k0, k0, MACH_CR_EXC_CODE    # Mask out the cause bits. 
  697.     addu    k0, k0, k1            # Get the address of the
  698.                         #    function entry.  Note that
  699.                         #    the cause is already 
  700.                         #    shifted left by 2 bits so
  701.                         #    we don't have to shift.
  702.     lw        k0, 0(k0)            # Get the function address
  703.     nop
  704.     j        k0                # Jump to the function.
  705.     nop
  706. .set at
  707. .set reorder
  708.  
  709. /*----------------------------------------------------------------------------
  710.  *
  711.  * Mach_UserGenException --
  712.  *
  713.  *    Handle an exception from user mode.
  714.  *
  715.  * Results:
  716.  *         None.
  717.  *
  718.  * Side effects:
  719.  *    None.
  720.  *
  721.  *----------------------------------------------------------------------------
  722.  */
  723. /*
  724.  * The user exception stack contains the status register and the exception
  725.  * PC.
  726.  */
  727. #define    USER_EXC_FRAME_SIZE    (4 + STAND_FRAME_SIZE)
  728. #define USER_SR_OFFSET        (STAND_RA_OFFSET + 4)
  729.  
  730. NON_LEAF(Mach_UserGenException,USER_EXC_FRAME_SIZE,ra)
  731. .set noreorder
  732. .set noat
  733. /*
  734.  * First of all switch over to the kernel gp.
  735.  */
  736.     addu    k1, gp, zero
  737.     la        gp, _gp
  738.     lw        k0, machCurStatePtr
  739.     nop
  740. /*
  741.  * Save all registers.
  742.  */
  743.     sw        sp, MACH_TRAP_REGS_OFFSET + (SP * 4)(k0)
  744.     sw        k1, MACH_TRAP_REGS_OFFSET + (GP * 4)(k0)
  745.     SAVE_REGS(k0, MACH_TRAP_REGS_OFFSET)
  746.     mflo    t0
  747.     sw        t0, MACH_TRAP_MULT_LO_OFFSET(k0)
  748.     mfhi    t0
  749.     sw        t0, MACH_TRAP_MULT_HI_OFFSET(k0)
  750. .set at
  751.  
  752. /*
  753.  * Change to the kernel's stack.
  754.  */
  755.     lw        sp, MACH_KERN_STACK_END_OFFSET(k0)
  756. /*
  757.  * Set up the stack frame.
  758.  */
  759.     mfc0    a3, MACH_COP_0_EXC_PC        # The fourth arg is the PC
  760.     subu    sp, sp, USER_EXC_FRAME_SIZE
  761.     sw        a3, STAND_RA_OFFSET(sp)
  762.     sw        a3, MACH_USER_PC_OFFSET(k0)
  763.     .mask    0x80000000, (STAND_RA_OFFSET - USER_EXC_FRAME_SIZE)
  764.  
  765.     mfc0    a0, MACH_COP_0_STATUS_REG    # First arg is the status reg.
  766.     nop
  767.     and        k1, a0, ~MACH_SR_COP_1_BIT    # Turn off the FPU.
  768.     mtc0    k1, MACH_COP_0_STATUS_REG
  769.     sw        k1, USER_SR_OFFSET(sp)
  770.  
  771. /*
  772.  * Call the handler.
  773.  */
  774.     mfc0    a1, MACH_COP_0_CAUSE_REG    # Second arg is the cause reg.
  775.     mfc0    a2, MACH_COP_0_BAD_VADDR    # Third arg is the fault addr
  776.     jal        MachUserExceptionHandler
  777.     nop
  778.  
  779. /*
  780.  * Restore user registers and return.  Interrupts are already disabled
  781.  * when MachUserExceptionHandler returns.
  782.  */
  783.     lw        k0, USER_SR_OFFSET(sp)
  784.     beq        v0, zero, 1f            # See if we are supposed to
  785.     nop                        #   to turn on the FPU.
  786.     or        k0, k0, MACH_SR_COP_1_BIT
  787. 1:
  788.     mtc0    k0, MACH_COP_0_STATUS_REG
  789.     lw        k0, machCurStatePtr
  790.     nop
  791. .set noat
  792.     lw        t0, MACH_TRAP_MULT_LO_OFFSET(k0)
  793.     lw        t1, MACH_TRAP_MULT_HI_OFFSET(k0)
  794.     mtlo    t0
  795.     mthi    t1
  796.     RESTORE_REGS(k0, MACH_TRAP_REGS_OFFSET)
  797.     lw        k1, MACH_USER_PC_OFFSET(k0)
  798.     nop
  799.     j        k1
  800.     rfe
  801. END(Mach_UserGenException)
  802. .set at
  803. .set reorder
  804.  
  805.  
  806. /*----------------------------------------------------------------------------
  807.  *
  808.  * Mach_EnableIntr --
  809.  *
  810.  *    Enable interrupts.
  811.  *
  812.  * Results:
  813.  *         None.
  814.  *
  815.  * Side effects:
  816.  *    Interrupts enabled.
  817.  *
  818.  *----------------------------------------------------------------------------
  819.  */
  820. LEAF(Mach_EnableIntr)
  821. .set noreorder
  822.     mfc0    t0, MACH_COP_0_STATUS_REG
  823.     nop
  824.     or        t0, t0, MACH_KERN_INT_MASK | MACH_SR_INT_ENA_CUR
  825.     mtc0    t0, MACH_COP_0_STATUS_REG
  826.     nop
  827.     j        ra
  828.     nop
  829. .set reorder
  830. END(Mach_EnableIntr)
  831.  
  832. /*----------------------------------------------------------------------------
  833.  *
  834.  * Mach_DisableIntr --
  835.  *
  836.  *    Disable Interrupts.
  837.  *
  838.  * Results:
  839.  *         None.
  840.  *
  841.  * Side effects:
  842.  *    Interrupts disabled.
  843.  *
  844.  *----------------------------------------------------------------------------
  845.  */
  846. LEAF(Mach_DisableIntr)
  847. .set noreorder
  848.     mfc0    t0, MACH_COP_0_STATUS_REG
  849.     nop
  850.     and        t0, t0, ~MACH_SR_INT_ENA_CUR
  851.     mtc0    t0, MACH_COP_0_STATUS_REG
  852.     nop
  853.     j        ra
  854.     nop
  855. .set reorder
  856. END(Mach_DisableIntr)
  857.  
  858. /*----------------------------------------------------------------------------
  859.  *
  860.  * Mach_ContextSwitch --
  861.  *
  862.  *    Mach_ContextSwitch(fromProcPtr, toProcPtr)
  863.  *
  864.  *    Perform a context switch.
  865.  *
  866.  * Results:
  867.  *         None.
  868.  *
  869.  * Side effects:
  870.  *    The current process's state is saved into its machine specific
  871.  *    process table entry and new state is loaded for the switched to
  872.  *    process.  
  873.  *
  874.  *----------------------------------------------------------------------------
  875.  */
  876. .set noreorder
  877.  
  878. NON_LEAF(Mach_ContextSwitch,STAND_FRAME_SIZE,ra)
  879.     subu    sp, sp, STAND_FRAME_SIZE
  880.     sw        ra, STAND_RA_OFFSET(sp)
  881.     sw        a0, STAND_FRAME_SIZE(sp)
  882.     sw        a1, STAND_FRAME_SIZE + 4(sp)
  883.     .mask    0x80000000, -4
  884. /*
  885.  * Set up this processes context.
  886.  */
  887.     addu    a0, a1, zero
  888.     jal        VmMach_SetupContext
  889.     nop
  890. /*
  891.  * Restore saved register values.
  892.  */
  893.     lw        ra, STAND_RA_OFFSET(sp)
  894.     lw        a0, STAND_FRAME_SIZE(sp)
  895.     lw        a1, STAND_FRAME_SIZE + 4(sp)
  896. /*
  897.  * Push the magic number and the status register onto the stack.
  898.  */
  899.     subu    sp, sp, 8
  900.     li        t0, MAGIC
  901.     sw        t0, 0(sp)
  902.     mfc0    t0, MACH_COP_0_STATUS_REG # Save the status reg.
  903.     nop
  904.     sw        t0, 4(sp)
  905.  
  906. /*
  907.  * Save the state of the current process.  We only have to save the saved
  908.  * register registers (s0 through s8) and the stack pointer.
  909.  */
  910.     lw        t0, machCurStatePtr
  911.     nop
  912.     addu    t0, t0, MACH_SWITCH_REGS_OFFSET
  913.     sw        a0, A0 * 4(t0)
  914.     sw        s0, S0 * 4(t0)
  915.     sw        s1, S1 * 4(t0)
  916.     sw        s2, S2 * 4(t0)
  917.     sw        s3, S3 * 4(t0)
  918.     sw        s4, S4 * 4(t0)
  919.     sw        s5, S5 * 4(t0)
  920.     sw        s6, S6 * 4(t0)
  921.     sw        s7, S7 * 4(t0)
  922.     sw        s8, S8 * 4(t0)
  923.     sw        ra, RA * 4(t0)
  924.     sw        sp, SP * 4(t0)
  925.     .globl Mach_SwitchPoint
  926. Mach_SwitchPoint:
  927.  
  928. /*
  929.  * Restore the registers for the new process.
  930.  */
  931.     lw        t0, machStatePtrOffset
  932.     nop
  933.     addu    t0, a1, t0
  934.     lw        t0, 0(t0)
  935.     nop
  936.     sw        t0, machCurStatePtr
  937.     addu    t1, t0, MACH_SWITCH_REGS_OFFSET
  938.     lw        a0, A0 * 4(t1)
  939.     lw        s0, S0 * 4(t1)
  940.     lw        s1, S1 * 4(t1)
  941.     lw        s2, S2 * 4(t1)
  942.     lw        s3, S3 * 4(t1)
  943.     lw        s4, S4 * 4(t1)
  944.     lw        s5, S5 * 4(t1)
  945.     lw        s6, S6 * 4(t1)
  946.     lw        s7, S7 * 4(t1)
  947.     lw        s8, S8 * 4(t1)
  948.     lw        ra, RA * 4(t1)
  949.     lw        sp, SP * 4(t1)
  950. /*
  951.  * Set up the maximum stack addr for the debugger.
  952.  */
  953.     lw        t1, MACH_KERN_STACK_END_OFFSET(t0)
  954.     nop
  955.     sw        t1, dbgMaxStackAddr
  956.  
  957. /*
  958.  * Wire down the current process's stack in the TLB.  This
  959.  * code depends implicitly upon MACH_KERN_STACK_PAGES.
  960.  */
  961.     mfc0    t1, VMMACH_TLB_HI
  962.  
  963. /*
  964.  * Map the first entry.
  965.  */
  966.     lw        t2, MACH_TLB_HIGH_ENTRY_OFFSET(t0)
  967.     lw        t3, MACH_TLB_LOW_ENTRY_1_OFFSET(t0)
  968.     li        t4, MACH_STACK_TLB_INDEX_1
  969.     mtc0    t2, VMMACH_TLB_HI
  970.     mtc0    t3, VMMACH_TLB_LOW
  971.     mtc0    t4, VMMACH_TLB_INDEX
  972.     nop
  973.     tlbwi
  974.  
  975. /*
  976.  * Map the second entry.
  977.  */
  978.     addu    t2, t2, 1 << VMMACH_TLB_VIRT_PAGE_SHIFT
  979.     lw        t3, MACH_TLB_LOW_ENTRY_2_OFFSET(t0)
  980.     li        t4, MACH_STACK_TLB_INDEX_2
  981.     mtc0    t2, VMMACH_TLB_HI
  982.     mtc0    t3, VMMACH_TLB_LOW
  983.     mtc0    t4, VMMACH_TLB_INDEX
  984.     nop
  985.     tlbwi
  986.  
  987. /*
  988.  * Map the third entry.
  989.  */
  990.     addu    t2, t2, 1 << VMMACH_TLB_VIRT_PAGE_SHIFT
  991.     lw        t3, MACH_TLB_LOW_ENTRY_3_OFFSET(t0)
  992.     li        t4, MACH_STACK_TLB_INDEX_3
  993.     mtc0    t2, VMMACH_TLB_HI
  994.     mtc0    t3, VMMACH_TLB_LOW
  995.     mtc0    t4, VMMACH_TLB_INDEX
  996.     nop
  997.     tlbwi
  998.  
  999.     mtc0    t1, VMMACH_TLB_HI
  1000.  
  1001. /*
  1002.  * Verify the magic number on the stack.
  1003.  */
  1004.     lw        t0, 0(sp)
  1005.     li        t1, MAGIC
  1006.     beq        t0, t1, 1f
  1007.     nop
  1008.     break    0
  1009.  
  1010. /*
  1011.  * Restore the status register and pop the stack.
  1012.  */
  1013. 1:
  1014.     lw        t0, 4(sp)
  1015.     nop
  1016.     mtc0    t0, MACH_COP_0_STATUS_REG
  1017.     addu    sp, sp, STAND_FRAME_SIZE + 8
  1018. /*
  1019.  * Return 
  1020.  */
  1021.     j        ra
  1022.     nop
  1023.  
  1024. END(Mach_ContextSwitch)
  1025. .set reorder
  1026.  
  1027. /*----------------------------------------------------------------------------
  1028.  *
  1029.  * Mach_GetPC --
  1030.  *
  1031.  *    Return the caller's PC.
  1032.  *
  1033.  * Results:
  1034.  *         The PC of the caller.
  1035.  *
  1036.  * Side effects:
  1037.  *    None.
  1038.  *
  1039.  *----------------------------------------------------------------------------
  1040.  */
  1041.     .globl Mach_GetPC
  1042. Mach_GetPC:
  1043.     addu    v0, ra, zero
  1044.     j        ra
  1045.  
  1046. /*----------------------------------------------------------------------------
  1047.  *
  1048.  * Mach_GetCallerPC --
  1049.  *
  1050.  *    Return the caller's caller's PC.
  1051.  *
  1052.  * Results:
  1053.  *         I have no idea how to do this, so return 0 for now.
  1054.  *
  1055.  * Side effects:
  1056.  *    None.
  1057.  *
  1058.  *----------------------------------------------------------------------------
  1059.  */
  1060.     .globl Mach_GetCallerPC
  1061. Mach_GetCallerPC:
  1062.     addu    v0, zero, zero
  1063.     j        ra
  1064.  
  1065. /*----------------------------------------------------------------------------
  1066.  *
  1067.  * Mach_TestAndSet --
  1068.  *
  1069.  *    Mach_TestAndSet(intPtr)
  1070.  *
  1071.  *    Return the caller's caller's PC.
  1072.  *
  1073.  * Results:
  1074.  *         0 for now.
  1075.  *
  1076.  * Side effects:
  1077.  *    None.
  1078.  *
  1079.  *----------------------------------------------------------------------------
  1080.  */
  1081. LEAF(Mach_TestAndSet)
  1082.     mfc0    t0, MACH_COP_0_STATUS_REG
  1083.     mtc0    zero, MACH_COP_0_STATUS_REG    # Disable interrupts
  1084.     lw        v0, 0(a0)            # Read out old value
  1085.     li        t1, 1
  1086.     sw        t1, 0(a0)            # Set value.
  1087.     mtc0    t0, MACH_COP_0_STATUS_REG    # Restore interrupts.
  1088.     j        ra
  1089. END(Mach_TestAndSet)
  1090.  
  1091. /*----------------------------------------------------------------------------
  1092.  *
  1093.  * Mach_EmptyWriteBuffer --
  1094.  *
  1095.  *    Mach_EmptyWriteBuffer()
  1096.  *
  1097.  *    Return when the write buffer is empty.
  1098.  *
  1099.  * Results:
  1100.  *         None.
  1101.  *
  1102.  * Side effects:
  1103.  *    None.
  1104.  *
  1105.  *----------------------------------------------------------------------------
  1106.  */
  1107. LEAF(Mach_EmptyWriteBuffer)
  1108.     nop
  1109.     nop
  1110.     nop
  1111.     nop
  1112. 1:    bc0f    1b
  1113.     j    ra
  1114. END(Mach_EmptyWriteBuffer)
  1115.  
  1116. #define SAVE_CP1_REG(reg) \
  1117.     swc1    $f/**/reg, MACH_FP_REGS_OFFSET+reg*4(a0)
  1118.  
  1119. #define REST_CP1_REG(reg) \
  1120.     lwc1    $f/**/reg, MACH_FP_REGS_OFFSET+reg*4(a1)
  1121.  
  1122. /*----------------------------------------------------------------------------
  1123.  *
  1124.  * MachSwitchFPState --
  1125.  *
  1126.  *    MachSwitchFPState(fromFPStatePtr, toFPStatePtr)
  1127.  *
  1128.  *    Save the current state into fromFPStatePtrs state and restore it
  1129.  *    from toFPStatePtr.
  1130.  *
  1131.  * Results:
  1132.  *         None.
  1133.  *
  1134.  * Side effects:
  1135.  *    None.
  1136.  *
  1137.  *----------------------------------------------------------------------------
  1138.  */
  1139. LEAF(MachSwitchFPState)
  1140.     subu    sp, sp, STAND_FRAME_SIZE
  1141.     sw    ra, STAND_RA_OFFSET(sp)
  1142.     .mask    0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
  1143.  
  1144.     mfc0    t1, MACH_COP_0_STATUS_REG    # Disable interrupts and
  1145.     li    t0, MACH_SR_COP_1_BIT        #    enable the coprocessor
  1146.     mtc0    t0, MACH_COP_0_STATUS_REG
  1147.  
  1148.     addu    t0, a0, 1    # If fromFPStatePtr is NIL then it will equal
  1149.     beq    t0, zero, 1f    #    zero if we add one to it.
  1150.  
  1151. .set noreorder
  1152. /*
  1153.  * First read out the status register to make sure that all FP operations
  1154.  * have completed.
  1155.  */
  1156.     cfc1    t0, MACH_FPC_CSR
  1157.     nop
  1158.     sw    t0, MACH_FP_SR_OFFSET(a0)
  1159. /* 
  1160.  * Save the floating point registers.
  1161.  */
  1162.     SAVE_CP1_REG(0); SAVE_CP1_REG(1); SAVE_CP1_REG(2); SAVE_CP1_REG(3)
  1163.     SAVE_CP1_REG(4); SAVE_CP1_REG(5); SAVE_CP1_REG(6); SAVE_CP1_REG(7)
  1164.     SAVE_CP1_REG(8); SAVE_CP1_REG(9); SAVE_CP1_REG(10); SAVE_CP1_REG(11)
  1165.     SAVE_CP1_REG(12); SAVE_CP1_REG(13); SAVE_CP1_REG(14); SAVE_CP1_REG(15)
  1166.     SAVE_CP1_REG(16); SAVE_CP1_REG(17); SAVE_CP1_REG(18); SAVE_CP1_REG(19)
  1167.     SAVE_CP1_REG(20); SAVE_CP1_REG(21); SAVE_CP1_REG(22); SAVE_CP1_REG(23)
  1168.     SAVE_CP1_REG(24); SAVE_CP1_REG(25); SAVE_CP1_REG(26); SAVE_CP1_REG(27)
  1169.     SAVE_CP1_REG(28); SAVE_CP1_REG(29); SAVE_CP1_REG(30); SAVE_CP1_REG(31)
  1170.  
  1171. 1:    
  1172. /*
  1173.  * Restore the floating point registers.
  1174.  */
  1175.     REST_CP1_REG(0); REST_CP1_REG(1); REST_CP1_REG(2); REST_CP1_REG(3)
  1176.     REST_CP1_REG(4); REST_CP1_REG(5); REST_CP1_REG(6); REST_CP1_REG(7)
  1177.     REST_CP1_REG(8); REST_CP1_REG(9); REST_CP1_REG(10); REST_CP1_REG(11)
  1178.     REST_CP1_REG(12); REST_CP1_REG(13); REST_CP1_REG(14); REST_CP1_REG(15)
  1179.     REST_CP1_REG(16); REST_CP1_REG(17); REST_CP1_REG(18); REST_CP1_REG(19)
  1180.     REST_CP1_REG(20); REST_CP1_REG(21); REST_CP1_REG(22); REST_CP1_REG(23)
  1181.     REST_CP1_REG(24); REST_CP1_REG(25); REST_CP1_REG(26); REST_CP1_REG(27)
  1182.     REST_CP1_REG(28); REST_CP1_REG(29); REST_CP1_REG(30); REST_CP1_REG(31)
  1183.  
  1184.     lw    t0, MACH_FP_SR_OFFSET(a1)
  1185.     nop
  1186.     and    t0, t0, ~MACH_FPC_EXCEPTION_BITS
  1187.     ctc1    t0, MACH_FPC_CSR
  1188.     nop
  1189.     mtc0    t1, MACH_COP_0_STATUS_REG    # Restore the status register.
  1190.  
  1191.     addu    sp, sp, STAND_FRAME_SIZE
  1192.  
  1193.     j    ra
  1194.     nop
  1195.  
  1196. .set reorder
  1197. END(MachSwitchFPState)
  1198.  
  1199. /*----------------------------------------------------------------------------
  1200.  *
  1201.  * MachGetCurFPState --
  1202.  *
  1203.  *    MachGetCurFPState(statePtr)
  1204.  *
  1205.  *    Save the current state into *statePtr.
  1206.  *
  1207.  * Results:
  1208.  *         None.
  1209.  *
  1210.  * Side effects:
  1211.  *    None.
  1212.  *
  1213.  *----------------------------------------------------------------------------
  1214.  */
  1215. LEAF(MachGetCurFPState)
  1216.     subu    sp, sp, STAND_FRAME_SIZE
  1217.     sw    ra, STAND_RA_OFFSET(sp)
  1218.     .mask    0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
  1219.  
  1220.     mfc0    t1, MACH_COP_0_STATUS_REG    # Disable interrupts and
  1221.     li    t0, MACH_SR_COP_1_BIT        #    enable the coprocessor
  1222.     mtc0    t0, MACH_COP_0_STATUS_REG
  1223.  
  1224. .set noreorder
  1225.     /*
  1226.      * First read out the status register to make sure that all FP
  1227.      * operations have completed.
  1228.      */
  1229.     cfc1    t0, MACH_FPC_CSR
  1230.     nop
  1231.     sw    t0, MACH_FP_SR_OFFSET(a0)
  1232.     /* 
  1233.      * Save the floating point registers.
  1234.      */
  1235.     SAVE_CP1_REG(0); SAVE_CP1_REG(1); SAVE_CP1_REG(2); SAVE_CP1_REG(3)
  1236.     SAVE_CP1_REG(4); SAVE_CP1_REG(5); SAVE_CP1_REG(6); SAVE_CP1_REG(7)
  1237.     SAVE_CP1_REG(8); SAVE_CP1_REG(9); SAVE_CP1_REG(10); SAVE_CP1_REG(11)
  1238.     SAVE_CP1_REG(12); SAVE_CP1_REG(13); SAVE_CP1_REG(14); SAVE_CP1_REG(15)
  1239.     SAVE_CP1_REG(16); SAVE_CP1_REG(17); SAVE_CP1_REG(18); SAVE_CP1_REG(19)
  1240.     SAVE_CP1_REG(20); SAVE_CP1_REG(21); SAVE_CP1_REG(22); SAVE_CP1_REG(23)
  1241.     SAVE_CP1_REG(24); SAVE_CP1_REG(25); SAVE_CP1_REG(26); SAVE_CP1_REG(27)
  1242.     SAVE_CP1_REG(28); SAVE_CP1_REG(29); SAVE_CP1_REG(30); SAVE_CP1_REG(31)
  1243.  
  1244.     mtc0    t1, MACH_COP_0_STATUS_REG    # Restore the status register.
  1245.  
  1246.     addu    sp, sp, STAND_FRAME_SIZE
  1247.  
  1248.     j    ra
  1249.     nop
  1250.  
  1251. .set reorder
  1252. END(MachGetCurFPState)
  1253.  
  1254. /*----------------------------------------------------------------------------
  1255.  *
  1256.  * MachFPInterrupt --
  1257.  *
  1258.  *    Handle a floating point interrupt.
  1259.  *
  1260.  * Results:
  1261.  *         MACH_OK
  1262.  *
  1263.  * Side effects:
  1264.  *    None.
  1265.  *
  1266.  *----------------------------------------------------------------------------
  1267.  */
  1268. NON_LEAF(MachFPInterrupt,STAND_FRAME_SIZE,ra)
  1269. /*
  1270.  *    unsigned statusReg;    (in a0)
  1271.  *    unsigned causeReg;    (in a1)
  1272.  *    Address EXC_pc;        (in a2)
  1273.  */
  1274.     subu    sp, sp, STAND_FRAME_SIZE
  1275.     sw    ra, STAND_RA_OFFSET(sp)
  1276.         sw    a2, STAND_FRAME_SIZE + 8(sp)
  1277.  
  1278.     and    t1, a0, MACH_SR_KU_PREV
  1279.     bne    t1, zero, 1f
  1280.     /*
  1281.      * We got an FPU interrupt in kernel mode.
  1282.      * At this point we should do something clever like
  1283.      * simulating the instruction that failed.  Instead
  1284.      * we just clear the FPU status register and let
  1285.      * the job die.
  1286.      */
  1287.     PRINTF("FPU interrupt in Kernel mode\012")
  1288.     /*
  1289.      * Turn on the floating point coprocessor.
  1290.      */
  1291.     mfc0    t0, MACH_COP_0_STATUS_REG
  1292.     or    t1, t0, MACH_SR_COP_1_BIT
  1293.     mtc0    t1, MACH_COP_0_STATUS_REG
  1294.     /*
  1295.      * Some nops are needed here or else the coprocessor
  1296.      * won't be enabled by the time we try to clear the
  1297.      * status register and the kernel will panic with
  1298.      * "coprocessor unusable".
  1299.      */
  1300.     nop
  1301.     nop
  1302.     nop
  1303.     nop
  1304.     /*
  1305.      * Clear the status register.
  1306.      */
  1307.     ctc1    zero, MACH_FPC_CSR
  1308.     j    FPReturn
  1309. 1:
  1310.     /*
  1311.      * Turn on the floating point coprocessor.
  1312.      */
  1313.     mfc0    t0, MACH_COP_0_STATUS_REG
  1314.     or    t1, t0, MACH_SR_COP_1_BIT
  1315.     mtc0    t1, MACH_COP_0_STATUS_REG
  1316.     /* 
  1317.      * Check for a stray interrupt.
  1318.      */
  1319.     lw    t1, machFPCurStatePtr
  1320.     lw    t2, machCurStatePtr
  1321.     beq    t1, t2, 1f
  1322.     /*
  1323.      * We got an interrupt and no one was using the coprocessor.  Clear
  1324.      * the interrupt and complain.
  1325.      */
  1326.     PRINTF("Stray FPU interrupt\012")
  1327.     ctc1    zero, MACH_FPC_CSR
  1328.     j    FPReturn
  1329. 1:
  1330.     /*
  1331.      * Fetch the instruction.
  1332.      */
  1333.     addu    v0, a1, 0
  1334.     bltz    v0, 3f                # Check the branch delay bit.
  1335.     /*
  1336.      * This is not in the branch delay slot so calculate the resulting
  1337.      * PC (epc + 4) into v0 and continue to softfp().
  1338.      */
  1339.     lw    a1, 0(a2)
  1340.     addu    v0, a2, 4
  1341.     lw    t0, machCurStatePtr
  1342.     sw    v0, MACH_USER_PC_OFFSET(t0)
  1343.     b    4f
  1344. 3:
  1345.     /*
  1346.      * This is in the branch delay slot so the branch will have to
  1347.      * be emulated to get the resulting PC.
  1348.      */
  1349.     lw    a0, machCurStatePtr
  1350.     addu    a0, a0, MACH_TRAP_REGS_OFFSET
  1351.     addu    a1, a2, zero
  1352.     cfc1    a2, MACH_FPC_CSR
  1353.     addu    a3, zero, zero
  1354.     jal    MachEmulateBranch    # MachEmulateBranch(regsPtr,instPC,csr,
  1355.                     #            FALSE)
  1356.     lw    t0, machCurStatePtr
  1357.     sw    v0, MACH_USER_PC_OFFSET(t0)
  1358.     /*
  1359.      * Now load the floating-point instruction in the branch delay slot
  1360.      * to be emulated by softfp().
  1361.      */
  1362.     lw    a2, STAND_FRAME_SIZE + 8(sp)    #EXC pc
  1363.     lw    a1, 4(a2)
  1364. 4:
  1365.     /*
  1366.      * Check to see if the instruction to be emulated is a floating-point
  1367.      * instruction.
  1368.      */
  1369.     srl    a3, a1, MACH_OPCODE_SHIFT
  1370.     beq    a3, MACH_OPCODE_C1, 5f
  1371.     /*
  1372.      * Send a floating point exception signal to the current process.
  1373.      */
  1374.     li    a0, MACH_SIGFPE
  1375.     jal    Mach_SendSignal
  1376.     j    FPReturn
  1377.  
  1378. 5:
  1379.     /*
  1380.      * Finally we can call softfp() where a1 has the instruction to
  1381.      * emulate.
  1382.      */
  1383.     jal    softfp
  1384.  
  1385. FPReturn:
  1386.     /*
  1387.      * Turn off the floating point coprocessor.
  1388.      */
  1389.     mfc0    t0, MACH_COP_0_STATUS_REG
  1390.     and    t0, t0, ~MACH_SR_COP_1_BIT
  1391.     mtc0    t0, MACH_COP_0_STATUS_REG
  1392.     /*
  1393.      * Return to our caller.
  1394.      */
  1395.     lw    ra, STAND_RA_OFFSET(sp)
  1396.     addu    sp, sp, STAND_FRAME_SIZE
  1397.     j    ra
  1398. END(MachFPInterrupt)
  1399.  
  1400. /*----------------------------------------------------------------------------
  1401.  *
  1402.  * MachSysCall --
  1403.  *
  1404.  *    MachSysCall --
  1405.  *
  1406.  *    Handle a system call.
  1407.  *
  1408.  * Results:
  1409.  *         None.
  1410.  *
  1411.  * Side effects:
  1412.  *    None.
  1413.  *
  1414.  *----------------------------------------------------------------------------
  1415.  */
  1416. .set noreorder
  1417.     .globl MachSysCall
  1418.     .ent MachSysCall, 0
  1419. MachSysCall:
  1420. /*
  1421.  * Check the magic number.
  1422.  */
  1423.     li        k0, MACH_SYSCALL_MAGIC
  1424.     bne        t1, k0, UNIXSyscall
  1425.     nop
  1426. 1:
  1427.     addu    t7, gp, zero            # Save the user's gp in t7
  1428.     la        gp, _gp                # Switch to the kernel's gp
  1429. /*
  1430.  * See if this system call is valid.
  1431.  */
  1432.     lw        t2, machMaxSysCall        # t2 <= Maximum sys call value.
  1433.     nop
  1434.     addu    t2, t2, 1            
  1435.     sltu    t2, t0, t2            # Is t0 < t2 ?    
  1436.     bne        t2, zero, 1f            # If so then continue on.
  1437.     nop
  1438. /*
  1439.  * System call number is too big.  Return SYS_INVALID_SYSTEM_CALL to
  1440.  * the user.
  1441.  */
  1442.     mfc0    t3, MACH_COP_0_EXC_PC
  1443.     addu    gp, t7, zero
  1444.     li        v0, 0x20002
  1445.     addu    t3, t3, 4
  1446.     j        t3
  1447.     rfe
  1448. /* 
  1449.  * Now we know that we have a good system call number so go ahead and
  1450.  * save state and switch to the kernel's stack.
  1451.  */
  1452. 1:
  1453.     lw        t1, machCurStatePtr
  1454.     addu    t2, sp, zero
  1455.     mfc0    t3, MACH_COP_0_EXC_PC
  1456.     sw        sp, MACH_TRAP_REGS_OFFSET + (SP * 4)(t1)
  1457.     sw        t7, MACH_TRAP_REGS_OFFSET + (GP * 4)(t1)
  1458.     sw        s0, MACH_TRAP_REGS_OFFSET + (S0 * 4)(t1)
  1459.     sw        s1, MACH_TRAP_REGS_OFFSET + (S1 * 4)(t1)
  1460.     sw        s2, MACH_TRAP_REGS_OFFSET + (S2 * 4)(t1)
  1461.     sw        s3, MACH_TRAP_REGS_OFFSET + (S3 * 4)(t1)
  1462.     sw        s4, MACH_TRAP_REGS_OFFSET + (S4 * 4)(t1)
  1463.     sw        s5, MACH_TRAP_REGS_OFFSET + (S5 * 4)(t1)
  1464.     sw        s6, MACH_TRAP_REGS_OFFSET + (S6 * 4)(t1)
  1465.     sw        s7, MACH_TRAP_REGS_OFFSET + (S7 * 4)(t1)
  1466.     sw        s8, MACH_TRAP_REGS_OFFSET + (S8 * 4)(t1)
  1467.     sw        ra, MACH_TRAP_REGS_OFFSET + (RA * 4)(t1)
  1468.     sw        t0, MACH_TRAP_REGS_OFFSET + (T0 * 4)(t1)
  1469.     sw        a0, MACH_TRAP_REGS_OFFSET + (A0 * 4)(t1)
  1470.     sw        a1, MACH_TRAP_REGS_OFFSET + (A1 * 4)(t1)
  1471.     sw        a2, MACH_TRAP_REGS_OFFSET + (A2 * 4)(t1)
  1472.     sw        a3, MACH_TRAP_REGS_OFFSET + (A3 * 4)(t1)
  1473.     sw        v0, MACH_TRAP_REGS_OFFSET + (V0 * 4)(t1)
  1474.     sw        v1, MACH_TRAP_REGS_OFFSET + (V1 * 4)(t1)
  1475.     sw        t3, MACH_USER_PC_OFFSET(t1)
  1476. /*
  1477.  * Change to the kernel's stack, enable interrupts and turn off the
  1478.  * floating point coprocessor.
  1479.  */
  1480.     mfc0    s8, MACH_COP_0_STATUS_REG
  1481.     lw        sp, MACH_KERN_STACK_END_OFFSET(t1)
  1482.     and        s8, s8, ~MACH_SR_COP_1_BIT
  1483.     or        t3, s8, MACH_SR_INT_ENA_CUR
  1484.     mtc0    t3, MACH_COP_0_STATUS_REG
  1485. /*
  1486.  * Now fetch the args.  The user's stack pointer is in t2.
  1487.  */
  1488.     sll        t0, t0, 2
  1489.     la        t3, machArgDispatch
  1490.     addu    t3, t0, t3
  1491.     lw        t3, 0(t3)
  1492.     nop
  1493.     jal        t3
  1494.     addu    v0, zero, zero
  1495.     bne        v0, zero, sysCallReturn
  1496.     addu    s0, t1, zero            # Save pointer to current state
  1497.                         #    in s0
  1498. /* 
  1499.  * We got the args now call the routine.
  1500.  */
  1501.     lw        s2, proc_RunningProcesses    # s2 <= pointer to running
  1502.                         #       processes array.
  1503.     lw        s1, machKcallTableOffset    # s1 <= Offset of kcall table
  1504.                         #       in proc table entry.
  1505.     lw        s2, 0(s2)            # s2 <= pointer to currently
  1506.     nop                        #       running process
  1507.     addu    s3, s2, s1            # s3 <= pointer to kcall table
  1508.                         #       pointer for currently
  1509.                         #       running    process
  1510.     addu    s1, s3, 4            # Special handling flag follows
  1511.                         # kcallTable field.  Save a 
  1512.                         # pointer to it in s1.
  1513.     lw        s3, 0(s3)            # s3 <= pointer to kcall table
  1514.     nop
  1515.     addu    s3, s3, t0            # s3 <= pointer to pointer to
  1516.                         #       function to call.
  1517.     lw        s3, 0(s3)            # s3 <= pointer to function.
  1518.     nop
  1519.     jal        s3                # Call the function
  1520.     nop
  1521. /*
  1522.  * Return to the user.  We have following saved information:
  1523.  *
  1524.  *    s0:    machCurStatePtr
  1525.  *    s1:    procPtr->specialHandling
  1526.  *    s2:    procPtr
  1527.  *    s8:    status register
  1528.  */
  1529. sysCallReturn:
  1530.     mtc0    s8, MACH_COP_0_STATUS_REG    # Disable interrupts.
  1531.     nop
  1532.     lw        t0, 0(s1)            # Get special handling flag.
  1533.     nop
  1534.     beq        t0, zero, checkFP        # See if special handling 
  1535.     nop                        #    required
  1536. /*
  1537.  * Need some special handling.
  1538.  */
  1539.     lw        t1, MACH_USER_PC_OFFSET(s0)    # Fetch return PC.
  1540.     or        t0, s8, MACH_SR_INT_ENA_CUR    # Prepare to enable interrupts.
  1541.     addu    t1, t1, 4            # Increment return PC by 4 to
  1542.                         #    get past the syscall inst.
  1543.     sw        t1, MACH_USER_PC_OFFSET(s0)    # Write back the return PC.
  1544.  
  1545.     mtc0    t0, MACH_COP_0_STATUS_REG    # Enable interrupts.
  1546.     sw        v0, MACH_TRAP_REGS_OFFSET + (V0 * 4)(s0)
  1547.  
  1548.     addu    a0, s2, zero
  1549.     jal        MachUserReturn            # Call MachUserReturn(procPtr)
  1550.     nop
  1551. /*
  1552.  * Restore A0, A1 and A2 because these will get changed if a signal handler
  1553.  * is to be called.
  1554.  */
  1555.     lw        k0, MACH_USER_PC_OFFSET(s0)
  1556.     lw        a0, MACH_TRAP_REGS_OFFSET + (A0 * 4)(s0)
  1557.     lw        a1, MACH_TRAP_REGS_OFFSET + (A1 * 4)(s0)
  1558.     lw        a2, MACH_TRAP_REGS_OFFSET + (A2 * 4)(s0)
  1559. /*
  1560.  * V1 and A3 are restored for UNIX binary compatibility.
  1561.  */
  1562.     lw        v1, MACH_TRAP_REGS_OFFSET + (V1 * 4)(s0)
  1563.     lw        a3, MACH_TRAP_REGS_OFFSET + (A3 * 4)(s0)
  1564.  
  1565.     beq        v0, zero, sysCallRestore
  1566.     lw        v0, MACH_TRAP_REGS_OFFSET + (V0 * 4)(s0)
  1567.     or        s8, s8, MACH_SR_COP_1_BIT
  1568.     j        sysCallRestore
  1569.     nop
  1570.  
  1571. checkFP:
  1572.     lw        k0, MACH_USER_PC_OFFSET(s0)
  1573.     lw        t0, machFPCurStatePtr
  1574.     addu    k0, k0, 4
  1575.     bne        t0, s0, sysCallRestore
  1576.     nop
  1577.     or        s8, s8, MACH_SR_COP_1_BIT
  1578.  
  1579. /*
  1580.  * Restore the registers.
  1581.  */
  1582.  
  1583. sysCallRestore:
  1584.     mtc0    s8, MACH_COP_0_STATUS_REG
  1585.     lw        sp, MACH_TRAP_REGS_OFFSET + (SP * 4)(s0)
  1586.     lw        gp, MACH_TRAP_REGS_OFFSET + (GP * 4)(s0)
  1587.     lw        s1, MACH_TRAP_REGS_OFFSET + (S1 * 4)(s0)
  1588.     lw        s2, MACH_TRAP_REGS_OFFSET + (S2 * 4)(s0)
  1589.     lw        s3, MACH_TRAP_REGS_OFFSET + (S3 * 4)(s0)
  1590.     lw        s4, MACH_TRAP_REGS_OFFSET + (S4 * 4)(s0)
  1591.     lw        s5, MACH_TRAP_REGS_OFFSET + (S5 * 4)(s0)
  1592.     lw        s6, MACH_TRAP_REGS_OFFSET + (S6 * 4)(s0)
  1593.     lw        s7, MACH_TRAP_REGS_OFFSET + (S7 * 4)(s0)
  1594.     lw        s8, MACH_TRAP_REGS_OFFSET + (S8 * 4)(s0)
  1595.     lw        ra, MACH_TRAP_REGS_OFFSET + (RA * 4)(s0)
  1596.     lw        s0, MACH_TRAP_REGS_OFFSET + (S0 * 4)(s0)
  1597. /*
  1598.  * Return.
  1599.  */
  1600.     j        k0
  1601.     rfe
  1602.  
  1603. .end MachSysCall
  1604. .set reorder
  1605.  
  1606. /*----------------------------------------------------------------------------
  1607.  *
  1608.  * UNIXSyscall --
  1609.  *
  1610.  *    Handle a new (compatibility) UNIX system call.
  1611.  *
  1612.  * Results:
  1613.  *         None.
  1614.  *
  1615.  * Side effects:
  1616.  *    None.
  1617.  *
  1618.  *----------------------------------------------------------------------------
  1619.  */
  1620. .set noreorder
  1621.     .globl UNIXSyscall
  1622.     .ent UNIXSyscall, 0
  1623. UNIXSyscall:
  1624. newUNIXSyscall:
  1625.     addu    t7, gp, zero            # Save the user's gp in t7
  1626.     la        gp, _gp                # Switch to the kernel's gp
  1627. /*
  1628.  * If we are tracing system calls or we have a signal or long jump return
  1629.  * do it the slow way.  Signal and long jump returns are done the slow way
  1630.  * because they have to do a full restore.
  1631.  */
  1632.     lw        k0, machUNIXSyscallTrace
  1633.     beq        v0, MACH_UNIX_LONG_JUMP_RETURN, Mach_UserGenException
  1634.     nop
  1635.     beq        v0, MACH_UNIX_SIG_RETURN, Mach_UserGenException
  1636.     nop
  1637.     bne        k0, zero, Mach_UserGenException
  1638. /*
  1639.  * See if this system call is valid.
  1640.  * Note: This is currently the actual entry point, since we jump out
  1641.  * of the middle of the old unix code.  This is so old/new can be
  1642.  * set on a call-by-call basis, by changing the table.
  1643.  */
  1644. doNewSysCall:
  1645.     sw          v0, sysCallNum
  1646. /* 
  1647.  * Save state and switch to the kernel's stack.  Note that we save 
  1648.  * a0 - a2 and v1 because UNIX system call stubs assume that these
  1649.  * won't get modified unless a value is returned in v1.
  1650.  */
  1651.     lw        t1, machCurStatePtr
  1652.     addu    t2, sp, zero
  1653.     mfc0    t3, MACH_COP_0_EXC_PC
  1654.     sw        v0, MACH_TRAP_UNIX_RET_VAL_OFFSET+4(t1)
  1655.     sw        a3, MACH_TRAP_UNIX_RET_VAL_OFFSET+8(t1)
  1656.     sw        sp, MACH_TRAP_REGS_OFFSET + (SP * 4)(t1)
  1657.     sw        t7, MACH_TRAP_REGS_OFFSET + (GP * 4)(t1)
  1658.     sw        s0, MACH_TRAP_REGS_OFFSET + (S0 * 4)(t1)
  1659.     sw        s1, MACH_TRAP_REGS_OFFSET + (S1 * 4)(t1)
  1660.     sw        s2, MACH_TRAP_REGS_OFFSET + (S2 * 4)(t1)
  1661.     sw        s3, MACH_TRAP_REGS_OFFSET + (S3 * 4)(t1)
  1662.     sw        s4, MACH_TRAP_REGS_OFFSET + (S4 * 4)(t1)
  1663.     sw        s5, MACH_TRAP_REGS_OFFSET + (S5 * 4)(t1)
  1664.     sw        s6, MACH_TRAP_REGS_OFFSET + (S6 * 4)(t1)
  1665.     sw        s7, MACH_TRAP_REGS_OFFSET + (S7 * 4)(t1)
  1666.     sw        s8, MACH_TRAP_REGS_OFFSET + (S8 * 4)(t1)
  1667.     sw        ra, MACH_TRAP_REGS_OFFSET + (RA * 4)(t1)
  1668.     sw        a0, MACH_TRAP_REGS_OFFSET + (A0 * 4)(t1)
  1669.     sw        a1, MACH_TRAP_REGS_OFFSET + (A1 * 4)(t1)
  1670.     sw        a2, MACH_TRAP_REGS_OFFSET + (A2 * 4)(t1)
  1671.     sw        v1, MACH_TRAP_REGS_OFFSET + (V1 * 4)(t1)
  1672.     sw        t3, MACH_USER_PC_OFFSET(t1)
  1673. /*
  1674.  * Change to the kernel's stack, enable interrupts and turn off the
  1675.  * floating point coprocessor.
  1676.  */
  1677.     mfc0    s8, MACH_COP_0_STATUS_REG
  1678.     lw        sp, MACH_KERN_STACK_END_OFFSET(t1)
  1679.     and        s8, s8, ~MACH_SR_COP_1_BIT
  1680.     or        t3, s8, MACH_SR_INT_ENA_CUR
  1681.     mtc0    t3, MACH_COP_0_STATUS_REG
  1682.  
  1683. /*
  1684.  *  Check if the call number is too big.  If so, set call to 0, since that
  1685.  *  is an invalid call.
  1686.  */
  1687.     sltu    t0, v0, MACH_MAX_UNIX_SYSCALL   # t0 <= Maximum sys call value.
  1688.     bne        t0, zero, 1f            # If so then continue on.
  1689.     nop
  1690.     addu    v0, zero, zero
  1691. /*
  1692.  * Now fetch the args.  The user's stack pointer is in t2 and the 
  1693.  * current state pointer in t1.
  1694.  */
  1695. 1:
  1696.     sll        t0, v0, 3    # t0 <= v0 * 8
  1697.     la        t3, sysUnixSysCallTable
  1698.     addu    t0, t0, t3
  1699.     lw        t3, 4(t0)    # t3 <= number of arguments.
  1700.     addu    s3, v0, zero    # Save syscall type in s3.
  1701.     addu    s1, t0, zero    # Save syscall index in s1
  1702.     sll        t3, t3, 2
  1703.     la        t4, machArgDispatchTable
  1704.     addu    t3, t3, t4
  1705.     lw        t3, 0(t3)    # t3 <= pointer to arg fetch routine.
  1706.     nop
  1707.     jal        t3
  1708.     addu    v0, zero, zero
  1709.     bne        v0, zero, unixNewSyscallReturn
  1710.     addu    s0, t1, zero            # Save pointer to current state
  1711.                         #    in s0
  1712.  
  1713. /* 
  1714.  * We got the args now call the routine.
  1715.  */
  1716.     lw        t3, 0(s1)    # t3 <= routine to call.
  1717.     nop
  1718.     jal        t3        # Call the routine.
  1719.     nop
  1720.  
  1721. /*
  1722.  * Return to the user.  We have the following saved information:
  1723.  *    s0:    machCurStatePtr
  1724.  * We have the following registers:
  1725.  *    v0: return value
  1726.  */
  1727. unixNewSyscallReturn:
  1728.     lw        s2, proc_RunningProcesses    # s2 <= pointer to running
  1729.                         #       processes array.
  1730.     lw        s1, machKcallTableOffset    # s1 <= Offset of kcall table
  1731.                         #       in proc table entry.
  1732.     lw        s2, 0(s2)            # s2 <= pointer to currently
  1733.                         #       running process
  1734.     addu    s1, s1, 4            # Special handling flag follows
  1735.                         # kcallTable field. 
  1736.     addu    s1, s2, s1            # s1 <= pointer to special
  1737.                         #       handling flag.
  1738. /*
  1739.  * We now have the following saved information:
  1740.  *
  1741.  *    s0:    machCurStatePtr
  1742.  *    s1:    procPtr->specialHandling
  1743.  *    s2:    procPtr
  1744.  */
  1745. /*
  1746.  * Set up the registers correctly:
  1747.  *
  1748.  *    1) Restore a0, a1, a2 and v1
  1749.  *    2) If status == 0 then regs[a3] <- 0 and v0 <- return value.
  1750.  *       Else regs[A3] <- 1 and v0 <- Compat_MapCode(status).
  1751.  */
  1752. 1:
  1753.     bltz    v0, 3f
  1754.     addu    a3, zero, zero
  1755. 2:
  1756.     lw        a0, MACH_TRAP_REGS_OFFSET + (A0 * 4)(s0)
  1757.     lw        a1, MACH_TRAP_REGS_OFFSET + (A1 * 4)(s0)
  1758.     lw        a2, MACH_TRAP_REGS_OFFSET + (A2 * 4)(s0)
  1759.     lw        v1, MACH_TRAP_REGS_OFFSET + (V1 * 4)(s0)
  1760.     sw        v0, MACH_TRAP_REGS_OFFSET + (V0 * 4)(s0)
  1761.     sw        a3, MACH_TRAP_REGS_OFFSET + (A3 * 4)(s0)
  1762.     j        sysCallReturn
  1763.     nop
  1764. 3:
  1765.     lw          v0, proc_RunningProcesses       # v0 <= pointer to running
  1766.                                                 #       processes array.
  1767.     nop
  1768.     lw          v0, 0(v0)                       # v0 <= pointer to currently
  1769.                                                 #       running process
  1770.     li          a3, 1
  1771.     lw          v0, MACH_UNIX_ERRNO_OFFSET(v0)
  1772.     nop
  1773.     j           2b
  1774.     nop
  1775.  
  1776. .end MachSysCall
  1777. .set reorder
  1778.  
  1779.     .globl MachFetchArgs
  1780. MachFetchArgs:
  1781. /*----------------------------------------------------------------------------
  1782.  *
  1783.  * MachFetch?Args --
  1784.  *
  1785.  *    Fetch the given number of arguments from the user's stack and put
  1786.  *    them onto the kernel's stack.  The user's stack pointer is in t2.
  1787.  *
  1788.  * Results:
  1789.  *         None.
  1790.  *
  1791.  * Side effects:
  1792.  *    None.
  1793.  *
  1794.  *----------------------------------------------------------------------------
  1795.  */
  1796. .set noreorder
  1797.     .globl MachFetch0Args
  1798. MachFetch0Args:
  1799.     j        ra
  1800.     subu    sp, sp, MACH_STAND_FRAME_SIZE
  1801.  
  1802.     .globl MachFetch1Arg
  1803. MachFetch1Arg:
  1804.     lw        s0, 16(t2)    
  1805.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 4
  1806.     j        ra
  1807.     sw        s0, 16(sp)
  1808.  
  1809.     .globl MachFetch2Args
  1810. MachFetch2Args:
  1811.     lw        s0, 16(t2)    
  1812.     lw        s1, 20(t2)
  1813.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 8
  1814.     sw        s0, 16(sp)
  1815.     j        ra
  1816.     sw        s1, 20(sp)
  1817.  
  1818.     .globl MachFetch3Args
  1819. MachFetch3Args:
  1820.     lw        s0, 16(t2)    
  1821.     lw        s1, 20(t2)
  1822.     lw        s2, 24(t2)
  1823.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 12
  1824.     sw        s0, 16(sp)
  1825.     sw        s1, 20(sp)
  1826.     j        ra
  1827.     sw        s2, 24(sp)
  1828.  
  1829.     .globl MachFetch4Args
  1830. MachFetch4Args:
  1831.     lw        s0, 16(t2)    
  1832.     lw        s1, 20(t2)
  1833.     lw        s2, 24(t2)
  1834.     lw        s3, 28(t2)
  1835.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 16
  1836.     sw        s0, 16(sp)
  1837.     sw        s1, 20(sp)
  1838.     sw        s2, 24(sp)
  1839.     j        ra
  1840.     sw        s3, 28(sp)
  1841.  
  1842.     .globl MachFetch5Args
  1843. MachFetch5Args:
  1844.     lw        s0, 16(t2)    
  1845.     lw        s1, 20(t2)
  1846.     lw        s2, 24(t2)
  1847.     lw        s3, 28(t2)
  1848.     lw        s4, 32(t2)
  1849.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 20
  1850.     sw        s0, 16(sp)
  1851.     sw        s1, 20(sp)
  1852.     sw        s2, 24(sp)
  1853.     sw        s3, 28(sp)
  1854.     j        ra
  1855.     sw        s4, 32(sp)
  1856.  
  1857.     .globl MachFetch6Args
  1858. MachFetch6Args:
  1859.     lw        s0, 16(t2)    
  1860.     lw        s1, 20(t2)
  1861.     lw        s2, 24(t2)
  1862.     lw        s3, 28(t2)
  1863.     lw        s4, 32(t2)
  1864.     lw        s5, 36(t2)
  1865.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 24
  1866.     sw        s0, 16(sp)
  1867.     sw        s1, 20(sp)
  1868.     sw        s2, 24(sp)
  1869.     sw        s3, 28(sp)
  1870.     sw        s4, 32(sp)
  1871.     j        ra
  1872.     sw        s5, 36(sp)
  1873.  
  1874. .set reorder
  1875.  
  1876.     .globl MachFetchArgsEnd
  1877. MachFetchArgsEnd:
  1878.  
  1879. /*
  1880.  * Beginning of area where the kernel should be able to handle a bus error
  1881.  * (which includes size errors) while in kernel mode.
  1882.  */
  1883.  
  1884. /*
  1885.  *----------------------------------------------------------------------
  1886.  *
  1887.  * Mach_Probe --
  1888.  *
  1889.  *    Copy a block of memory from one virtual address to another handling
  1890.  *    bus errors that may occur. This    routine is intended to be used to 
  1891.  *    probe for memory mapped devices.
  1892.  *
  1893.  *    The memory interrupt must be enabled for this thing to work.
  1894.  *
  1895.  *    The ds5000 has a few quirks that make this all more complicated
  1896.  *    then it has to be.  First of all, accesses to unpopulated memory
  1897.  *    addresses don't seem to cause any sort of error, so you can't
  1898.  *    use Mach_Probe to figure out how much memory you have.  Second,
  1899.  *    an access to an invalid IO address causes an interrupt.
  1900.  *    Therefore you need to have the memory interrupt enabled to get
  1901.  *    this to work.  A read of an invalid IO address causes both a bus error
  1902.  *    and an interrupt.  The bus error handler will just ignore the bus
  1903.  *    error if it happened in Mach_Probe.  This may not be the best solution
  1904.  *    but it seems to work.
  1905.  *
  1906.  * NOTE: This trap handlers force this routine to return SYS_NO_ACCESS if an
  1907.  *     bus error occurs.
  1908.  *
  1909.  * Calling sequences:
  1910.  *
  1911.  * ReturnStatus
  1912.  * Mach_Probe(size, srcAddress, destAddress)
  1913.  *    int        size;     Size in bytes of the read to do. Must
  1914.  *                  1, 2, 4, or 8  
  1915.  *  Address    srcAddress;     Address to read from. 
  1916.  *  Address    destAddress;     Address to store the read value. 
  1917.  *    
  1918.  *
  1919.  * Results:
  1920.  *    SUCCESS if the copy worked, SYS_NO_ACCESS if there was a bus
  1921.  *    error or IO timeout, FAILURE if the memory interrupt is
  1922.  *    disabled
  1923.  *
  1924.  * Side effects:
  1925.  *    None.
  1926.  *----------------------------------------------------------------------
  1927.  */
  1928. .set noreorder
  1929.     .globl Mach_Probe
  1930.     .ent Mach_Probe, 0
  1931. Mach_Probe:
  1932.     /* a0 is the number of bytes
  1933.      * a1 is the src address
  1934.      * a2 is the dest address
  1935.      */
  1936.     bne     a0,1, Read2Bytes
  1937.     nop
  1938.     lbu     t0, 0(a1)
  1939.     nop
  1940.     sb    t0, 0(a2)
  1941.     j    ra
  1942.     addu    v0, zero, zero
  1943. Read2Bytes:
  1944.     bne     a0, 2, Read4Bytes
  1945.     nop
  1946.     and    t0, a1, 0x1
  1947.     bne    t0, zero, BadRead
  1948.     nop
  1949.     and    t0, a2, 0x1
  1950.     bne    t0, zero, BadRead
  1951.     nop
  1952.     lhu    t0, 0(a1)
  1953.     nop
  1954.     sh    t0, 0(a2)
  1955.     j    ra
  1956.     addu    v0, zero, zero
  1957. Read4Bytes:
  1958.     bne     a0, 4, Read8Bytes
  1959.     nop
  1960.     and    t0, a1, 0x3
  1961.     bne    t0, zero, BadRead
  1962.     nop
  1963.     and    t0, a2, 0x3
  1964.     bne    t0, zero, BadRead
  1965.     nop
  1966.     lw    t0, 0(a1)
  1967.     nop
  1968.     sw    t0, 0(a2)
  1969.     j    ra
  1970.     addu    v0, zero, zero
  1971. Read8Bytes:
  1972.     bne     a0, 8, BadRead
  1973.     nop
  1974.     and    t0, a1, 0x7
  1975.     bne    t0, zero, BadRead
  1976.     nop
  1977.     and    t0, a2, 0x7
  1978.     bne    t0, zero, BadRead
  1979.     nop
  1980.     lw    t0, 0(a1)
  1981.     nop
  1982.     sw    t0, 0(a2)
  1983.     lw    t0, 4(a1)
  1984.     nop    
  1985.     sw    t0, 4(a1)
  1986.     j    ra
  1987.     addu    v0, zero, zero
  1988. BadRead:
  1989.     j    ra
  1990.     addu    v0, zero, 1
  1991. .set reorder
  1992.  
  1993.     .globl    MachProbeEnd
  1994. MachProbeEnd:
  1995. .end
  1996.